<template>
	<view class="app-popup" :class="type">
		<uniTransition v-if="status.maskShow" :show="props.modelValue" :styles="status.maskClass" @click="onTap"
			modeClass="fade" :duration="durationTemp">
		</uniTransition>
		<uniTransition :show="props.modelValue" :styles="transClass" @click="onTap" :modeClass="status.modeClass"
			@change="tranChange" :duration="durationTemp">
			<view class="app-popup-wrapper" :class="props.type" :style="{ backgroundColor: bg}" @click.stop="clear">
				<slot></slot>
			</view>
		</uniTransition>
	</view>
</template>

<script setup lang="ts" name="AppPopup">
/**
 * PopUp 弹出层
 * @description 弹出层组件，为了解决遮罩弹层的问题
 * @property {Boolean} modelValue 是否展示
 * @property {String} type = [top|center|bottom|left|right] 弹出方式
 * 	@value top 顶部弹出
 * 	@value center 中间弹出
 * 	@value bottom 底部弹出
 * 	@value left		左侧弹出
 * 	@value right  右侧弹出
 * @property {Boolean} isMaskClick = [true|false] 蒙版点击是否关闭弹窗
 * @property {String}  backgroundColor 主窗口背景色
 * @property {String}  maskBackgroundColor 蒙版颜色
 * @property {Boolean} safeArea		   是否适配底部安全区
 * @event {Function} close 打开关闭弹窗触发，e={show: false,type: [top|center|bottom|left|right]}
 * @event {Function} maskClick 点击遮罩触发
 */
import uniTransition from "@/uni_modules/uni-transition/components/uni-transition/uni-transition.vue";

export interface AppPopupProps {
	modelValue: boolean
	type: "top" | "bottom" | "center" | "left" | "right"
	animation?: boolean
	duration?: number
	isMaskClick?: boolean
	backgroundColor?: string
	maskBackgroundColor?: string
	// safeArea?: boolean
}
export interface AppPopupEmits {
	(e: 'update:modelValue', val: AppPopupProps['modelValue']): void
	(e: 'close', data: {
		/**弹出状态 */
		value: AppPopupProps['modelValue'],
		/**弹出方式 */
		type: AppPopupProps['type']
	}): void
	(e: 'maskClick'): void
}

const props = withDefaults(defineProps<AppPopupProps>(), {
	animation: true,
	duration: 300,
	isMaskClick: true,
	backgroundColor: '#fff',
	maskBackgroundColor: 'rgba(0, 0, 0, 0.4)',
	// safeArea: true,
})
const emit = defineEmits<AppPopupEmits>()

const status = reactive({
	maskShow: true,
	maskClass: {
		position: 'fixed',
		bottom: 0,
		top: 0,
		left: 0,
		right: 0,
		backgroundColor: 'rgba(0, 0, 0, 0.4)'
	},
	modeClass: ['fade'],
})

/**计算类型样式 */
const transClass = computed(() => {
	let data: Record<string, string | number> = {
		position: 'fixed'
	}
	if (props.type == 'top') {
		status.modeClass = ['slide-top']
		data = {
			...data,
			left: 0,
			right: 0,
			top: 0,
			backgroundColor: bg.value
		}
	}
	if (props.type == 'bottom') {
		status.modeClass = ['slide-bottom']
		data = {
			...data,
			left: 0,
			right: 0,
			bottom: 0,
			backgroundColor: bg.value
		}
	}
	if (props.type == 'center') {
		status.modeClass = ['zoom-in', 'fade']
		data = {
			...data,
			left: 0,
			right: 0,
			top: 0,
			bottom: 0,
			display: 'flex',
			flexDirection: 'column',
			justifyContent: 'center',
			alignItems: 'center'
		}
	}
	if (props.type == 'left') {
		status.modeClass = ['slide-left']
		data = {
			...data,
			left: 0,
			bottom: 0,
			top: 0,
		}
	}
	if (props.type == 'right') {
		status.modeClass = ['slide-right']
		data = {
			...data,
			right: 0,
			bottom: 0,
			top: 0,
		}
	}
	return data
})
/**计算盒子内的背景色 */
const bg = computed(() => {
	if (props.backgroundColor === '' || props.backgroundColor === 'none') {
		return 'transparent'
	}
	return props.backgroundColor
})
/**计算动画时间 */
const durationTemp = computed(() => {
	if (!props.animation) {
		return 0
	}
	return props.duration
})
/**点击遮罩时触发的事件 */
const onTap = () => {
	emit('maskClick')
	if (!props.isMaskClick) return
	close()
}

/**关闭弹出层关闭 */
const close = () => {
	emit('update:modelValue', false)
}
const clear = (e: MouseEvent) => {
	e.stopPropagation()
}

//动画切换
const tranChange = (e: { detail: boolean }) => {
	if (!e.detail) {
		emit('update:modelValue', false)
		emit('close', {
			value: false,
			type: props.type
		})
	}
}
</script>

<style scoped lang="scss">
.app-popup {
	position: fixed;
	z-index: 99;

	.app-popup-wrapper {
		position: relative;
		height: 100%;
		max-height: 100vh;
		overflow: auto;

		&.center {
			height: auto;
		}
	}
}
</style>